using System;
using System.Collections.Generic;
using System.Text;
using GameFramework;
using GameEngine;


namespace Projet_X0
{
    class Projectile : Entity
    {
        private float portee = 0f;
        private Speed speed = null;
        private Position position = null;
        private Orientation orientation = null;
        private MoveFront moveFront = null;
        private Update update = null;
        private Collidable collidable = null;
        private float damage = 0f;
        private CheckCollision checkCollision = null;
        
        public Projectile(float portee, int speed, Vector2D position, float direction, float damage)
            : base((int)EntityID.Projectile)
        {
            this.damage = damage;
            this.portee = portee;
            this.speed = new Speed(speed);
            AddState(this.speed);
            this.position = new Position(position);
            AddState(this.position);
            this.orientation = new Orientation(direction);
            AddState(orientation);
            collidable = new Collidable(this);
            AddState(collidable);
            moveFront = new MoveFront(this);
            moveFront.Activate(true);
            checkCollision = new CheckCollision(this);
            checkCollision.Activate(true);
            update = new Update(this);
            update.Activate(true);
            form = new ProjectileForm(this);
        }

        public Position GetPosition()
        {
            return position;
        }

        public void SetPortee(float portee)
        {
            this.portee = portee;
        }
                
        public void Die()
        {
             Terminate();
        }

        public float GetPortee()
        {
            return portee;
        }

        public float GetDamage()
        {
            return damage;
        }

        public override void Terminate()
        {
            checkCollision.Terminate();
            moveFront.Terminate();
            update.Terminate();

            base.Terminate();
        }

        private class CheckCollision : Action
        {
            public CheckCollision(Entity source)
                : base(source)
            {
            }

            public override void Run()
            {
                Projectile projectile = (Projectile)source;
                Collidable collidable = (Collidable)projectile.GetState((int)StatesID.Collidable);
                List<Entity> entities = collidable.GetCollidable().GetCollisions();
                bool collision = false;
                for (int i = 0; i < entities.Count; i++)
                {
                    Character.Health health = (Character.Health)entities[i].GetState((int)StatesID.Health);
                    if (health != null)
                    {
                        health.TakeDamage(projectile.GetDamage());
                        collision = true;
                    }
                }
                if (collision)
                    projectile.Die();
            }
        }

        private class MoveFront : Action
        {
            public MoveFront(Entity source)
                : base(source)
            {
            }

            public override void Run()
            {
                Projectile projectile = (Projectile)source;
                Position position = (Position)projectile.GetState((int)StatesID.Position);
                Orientation orientation = (Orientation)source.GetState((int)StatesID.Orientation);
                Speed speed = (Speed)source.GetState((int)StatesID.Speed);
                position.Set(new Vector2D((float)(position.GetPos().GetX() + Math.Sin(orientation.Get()) * speed.Get()), (float)(position.GetPos().GetY() - Math.Cos(orientation.Get()) * speed.Get())));

            }
        }

        private class Update : Action
        {
            public Update(Entity source)
                : base(source)
            {
            }

            public override void Run()
            {
                Projectile projectile = (Projectile)source;
                Speed speed = (Speed)projectile.GetState((int)StatesID.Speed);
                projectile.SetPortee(projectile.GetPortee() - speed.Get());
                if (projectile.GetPortee() <= 0)
                    projectile.Die();
            }
        }
    }
}
